import base64
import datetime
import logging
import random
import ssl
import string
from urllib.parse import parse_qs

from alipay import AliPay
from django.core import serializers, paginator
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.db.models import F
from django.http import JsonResponse
from django.shortcuts import render, redirect, HttpResponse
from django.views.decorators.csrf import csrf_exempt

from it_alipay.models import PayOrder
from users.models import UserProfile
from utils.dateutil import get_today_month

import json
import time

from utils.request_decorator import request_auth


# logging.basicConfig(level=logging.DEBUG,
#                     format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
#                     datefmt='%a, %d %b %Y %H:%M:%S',
#                     filename='/var/log/django/alipay.log',
#                     filemode='a')


def get_ali_object():
    # 沙箱环境地址：https://openhome.alipay.com/platform/appDaily.htm?tab=info
    app_id = "2018121762553950"  #  APPID （正式应用）

    # 支付完成后，支付偷偷向这里地址发送一个post请求，识别公网IP,如果是 192.168.20.13局域网IP ,支付宝找不到，def page2() 接收不到这个请求
    notify_url = "http://imagethinking.semyes.cn/pay_finish_page/"
    # notify_url = "http://127.0.0.1:8000/pay_finish_page/"

    # 支付完成后，跳转的地址。
    return_url = "http://imagethinking.semyes.cn/pay_finish_page/"
    # return_url = "http://127.0.0.1:8000/pay_finish_page/"

    merchant_private_key_path = "keys/app_private_2048.txt" # 应用私钥
    alipay_public_key_path = "keys/alipay_public_2048.txt"  # 支付宝公钥

    alipay = AliPay(
        appid=app_id,
        app_notify_url=notify_url,
        app_private_key_path=merchant_private_key_path,
        alipay_public_key_path=alipay_public_key_path,  # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥
        # debug=True,  # 默认False,
    )
    return alipay


def pay_index(request):
    return render(request, 'pay_templates/index.html')


def alipay_check(alipay, out_trade_no):
    # 调用alipay工具查询支付结果，判断此订单是否已支付
    # https://docs.open.alipay.com/api_1/alipay.trade.query
    ssl._create_default_https_context = ssl._create_unverified_context
    response = alipay.api_alipay_trade_query(out_trade_no)  # response是一个字典

    return response


@csrf_exempt
@request_auth
def pay_page(request):
    # 支付完成后，支付偷偷向这里地址发送一个post请求，识别公网IP,如果是 192.168.20.13局域网IP ,支付宝找不到，def page2() 接收不到这个请求
    notify_url = "http://imagethinking.semyes.cn/pay_finish_page/"
    # notify_url = "http://127.0.0.1:8000/pay_finish_page/"

    # 支付完成后，跳转的地址。
    return_url = "http://imagethinking.semyes.cn/pay_finish_page/"
    # return_url = "http://127.0.0.1:8000/pay_finish_page/"

    # 根据当前用户的配置，生成URL，并跳转。
    money = 0.01
    vip_type = float(request.POST.get('type'))

    if vip_type == 1:
        money = 0.01
        vip_version = '个人专业版99元/月'

    salt = ''.join(random.sample(string.ascii_letters + string.digits, 8))
    out_trade_no = salt + str(int(time.time() * 10000000)) + str(random.randint(1000, 9999))

    alipay = get_ali_object()

    auth_token = request.COOKIES.get('tooken')
    payload = auth_token.split(".")[1] + "=="
    a = base64.b64decode(payload).decode('unicode_escape')
    user_info = json.loads(a)
    user_id = user_info.get("user_id")

    pay_order = PayOrder(user_id=user_id, vip_version=vip_version, out_trade_no=out_trade_no, status=0)
    pay_order.save()

    # 生成支付的url
    query_params = alipay.api_alipay_trade_page_pay(
        subject="ImageThinking会员充值",  # 商品简单描述
        out_trade_no=out_trade_no,  # 用户购买的商品订单号（每次不一样） 20180301073422891
        total_amount=money,  # 交易金额(单位: 元 保留俩位小数)
        return_url=return_url,
        notify_url=notify_url  # 可选, 不填则使用默认notify url
    )

    # pay_url = "https://openapi.alipaydev.com/gateway.do?{0}".format(query_params)  # 支付宝网关地址（沙箱应用）
    pay_url = "https://openapi.alipay.com/gateway.do?{0}".format(query_params)  # 支付宝网关地址（正式应用）

    return JsonResponse({"code": 0, "message": "请求支付成功", "url": pay_url})


@csrf_exempt
# @request_auth
def pay_finish_page(request):
    alipay = get_ali_object()
    logging.debug(request.body.decode('utf-8'))
    logging.debug(request.method)
    if request.method == "POST":  # TRADE_SUCCESS,支付了才会触发通知
        try:
            # 检测是否支付成功
            # 去请求体中获取所有返回的数据：状态/订单号
            # POST方法后台回调，只能在外网服务器测试
            body_str = request.body.decode('utf-8')
            post_data = parse_qs(body_str)

            post_dict = {}
            for k, v in post_data.items():
                post_dict[k] = v[0]

            # post_dict有10key： 9 ，1
            sign = post_dict.pop('sign', None)
            status = alipay.verify(post_dict, sign)  # 验签

            logging.debug(status)

            out_trade_no = post_dict['out_trade_no']

            response = alipay_check(alipay, out_trade_no)

            logging.debug(response)

            # 判断支付结果
            code = response.get("code")  # 支付宝接口调用成功或者错误的标志
            trade_no = response.get("trade_no")  # 支付宝交易号
            buyer_user_id = response.get("buyer_user_id")  # 买家在支付宝的用户id
            total_amount = response.get("total_amount")  # 交易的订单金额，单位为元，两位小数。
            trade_status = response.get("trade_status")  # 用户支付的情况，交易状态
            send_pay_date = response.get("send_pay_date")  # 本次交易打款给卖家的时间

            if code == "10000" and trade_status == "TRADE_SUCCESS":

                pay_order = PayOrder.objects.filter(out_trade_no=out_trade_no)

                logging.debug(pay_order)
                logging.debug(pay_order[0].status)

                # 表示用户支付成功
                # 返回前端json，通知支付成功
                if pay_order.count() > 0 and pay_order[0].status == 0:
                    one_more_month = get_today_month(send_pay_date, 1)

                    try:
                        # 更新订单信息
                        pay_order.update(total_amount=total_amount,
                                         trade_no=trade_no,
                                         seller_id=buyer_user_id,
                                         status=1,
                                         start_time=send_pay_date,
                                         finish_time=one_more_month
                                         )

                        # 更新用户信息
                        user = UserProfile.objects.filter(id=pay_order[0].user_id)
                        if user[0].pay_times >= 1:
                            user.update(vip=1,
                                        renewal_time=send_pay_date,
                                        finish_time=one_more_month,
                                        pay_times=F("pay_times") + 1
                                        )
                        else:
                            user.update(vip=1,
                                        start_time=send_pay_date,
                                        renewal_time=send_pay_date,
                                        finish_time=one_more_month,
                                        pay_times=F("pay_times") + 1
                                        )
                    except Exception as e:
                        logging.debug(e)
        except Exception as e:
            logging.debug(e)

        return JsonResponse({"code": 0, "message": "POST支付成功", "out_trade_no": out_trade_no, 'post_data': post_data})

    else:
        params = request.GET.dict()

        auth_token = request.COOKIES.get('tooken')
        payload = auth_token.split(".")[1] + "=="
        a = base64.b64decode(payload).decode('unicode_escape')
        user_info = json.loads(a)
        user_id = user_info.get("user_id")

        try:

            logging.debug(params['out_trade_no'])

            response = alipay_check(alipay, params['out_trade_no'])

            # 判断支付结果
            code = response.get("code")  # 支付宝接口调用成功或者错误的标志
            trade_no = response.get("trade_no")  # 支付宝交易号
            buyer_user_id = response.get("buyer_user_id")  # 买家在支付宝的用户id
            total_amount = response.get("total_amount")  # 交易的订单金额，单位为元，两位小数。
            trade_status = response.get("trade_status")  # 用户支付的情况，交易状态
            send_pay_date = response.get("send_pay_date")  # 本次交易打款给卖家的时间

            if code == "10000" and trade_status == "TRADE_SUCCESS":

                pay_order = PayOrder.objects.filter(user_id=user_id, out_trade_no=params['out_trade_no'])

                if pay_order.count() > 0 and pay_order[0].status == 0:
                    one_more_month = get_today_month(send_pay_date, 1)

                    try:
                        # 更新订单信息
                        pay_order.update(total_amount=total_amount,
                                         trade_no=trade_no,
                                         seller_id=buyer_user_id,
                                         status=1,
                                         start_time=send_pay_date,
                                         finish_time=one_more_month
                                         )

                        # 更新用户信息
                        user = UserProfile.objects.filter(id=pay_order[0].user_id)
                        if user[0].pay_times >= 1:
                            user.update(vip=1,
                                        renewal_time=send_pay_date,
                                        finish_time=one_more_month,
                                        pay_times=F("pay_times") + 1
                                        )
                        else:
                            user.update(vip=1,
                                        start_time=send_pay_date,
                                        renewal_time=send_pay_date,  # 续期时间
                                        finish_time=one_more_month,
                                        pay_times=F("pay_times") + 1
                                        )
                    except Exception as e:
                        print(e)
                        user = UserProfile.objects.filter(id=user_id)
                        if user[0].vip == 0:
                            # 判断过期时间是不是大于现在
                            if datetime.datetime.strptime(one_more_month, "%Y-%m-%d %H:%M:%S") \
                                    > datetime.datetime.now():
                                user.update(
                                    vip=1,
                                    renewal_time=send_pay_date,
                                    finish_time=one_more_month,
                                    pay_times=F("pay_times") + 1
                                    )
                        else:
                            user.update(
                                        renewal_time=send_pay_date,
                                        finish_time=one_more_month,
                                        pay_times=F("pay_times") + 1
                                        )

                        if pay_order.count() > 0 and pay_order[0].status == 0:
                            # 更新订单信息
                            pay_order.update(total_amount=total_amount,
                                             trade_no=trade_no,
                                             seller_id=buyer_user_id,
                                             status=1,
                                             start_time=send_pay_date,
                                             finish_time=one_more_month
                                             )
        except Exception as e:
            print(e)
        # sign = params.pop('sign', None)
        # print(sign)
        # print(params)
        # status = alipay.verify(params, sign)  # 验签
        # print('==================开始==================')
        # print('GET验证', status)
        # print('==================结束==================')
        # return HttpResponse('支付成功')
        return redirect('/pay_order_page/')


@csrf_exempt
@request_auth
def pay_order_page(request):
    return render(request, 'html/main/order_record_1.html')


@csrf_exempt
@request_auth
def order_record(request):
    page = request.GET.get('page')
    if page is None or page == '':
        page = 1

    auth_token = request.COOKIES.get('tooken')
    payload = auth_token.split(".")[1] + "=="
    a = base64.b64decode(payload).decode('unicode_escape')
    user_info = json.loads(a)
    user_id = user_info.get("user_id")

    # .values_list('trade_no', 'start_time', 'vip_version', 'total_amount')
    orders = PayOrder.objects.filter(user_id=user_id,status=1).order_by('-start_time')

    order_page = Paginator(orders, 10)

    try:
        choise_page = order_page.page(page)  # 获取某页对应的记录
    except PageNotAnInteger:  # 如果页码不是个整数
        choise_page = order_page.page(1)  # 取第一页的记录
    except EmptyPage:  # 如果页码太大，没有相应的记录
        choise_page = order_page.page(order_page.num_pages)  # 取最后一页的记录

    page_num = order_page.num_pages

    return JsonResponse({"code": 0, "message": "支付订单",
                        "data": json.loads(serializers.serialize('json', choise_page)),
                         'page_num': page_num, 'current_page': page, 'total_counts': order_page.count})

@csrf_exempt
@request_auth
def set_meal_test(request):
    return render(request, 'html/main/set_meal2.html')